package com.msh.frame.web.wrapper;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.function.Function;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class BodyFunctionHttpServletRequestWrapper extends HttpServletRequestWrapper {
  private final String body;
  private final Function<String, String> function;

  public BodyFunctionHttpServletRequestWrapper(HttpServletRequest request, Function<String, String> function) {
    super(request);
    this.function = function;
    StringBuilder sb = new StringBuilder(128);
    BufferedReader br = null;
    try(InputStream is = request.getInputStream()){
      if (is != null) {
        br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
        char[] charBuffer = new char[128];
        int byteRead = -1;
        while ((byteRead = br.read(charBuffer)) > 0) {
          sb.append(charBuffer, 0, byteRead);
        }
      }
    } catch (IOException e) {
      log.error("请求读取错误", e.getMessage());
    }
    String oldBody = sb.toString();
    this.body = function.apply(oldBody);
    log.debug("请求body->执行前: {}, 执行后: {}", oldBody, this.body);
  }

  @Override
  public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
    ServletInputStream servletInputStream = new ServletInputStream() {
      @Override
      public boolean isFinished() {
        return false;
      }

      @Override
      public boolean isReady() {
        return false;
      }

      @Override
      public void setReadListener(ReadListener readListener) {

      }

      @Override
      public int read() throws IOException {
        return byteArrayInputStream.read();
      }
    };
    return servletInputStream;
  }

  @Override
  public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream()));
  }

}
